/*
 *  Yi Jin A53009661
 */
#ifndef PREFETCHER_H
#define PREFETCHER_H

#include <sys/types.h>
#include "mem-sim.h"
using namespace std;
#include <queue>
const int EPOCH = 80;
const int FETCH = 4;
const int FILTER_SIZE = 80;
const int MAX_STREAM = 80;
const int QUEUE_SIZE = 12;
const int MAX_LENGTH = 40;
const int LIFETIME = 24;
struct StreamFilterSlot
{
	u_int32_t addr;
	int length;
	int life;
	bool direction;
};
class StreamFilter
{
	private:
		StreamFilterSlot streamFilterSlots[FILTER_SIZE];
		u_int32_t LHTcurr[MAX_STREAM];
		u_int32_t LHTnext[MAX_STREAM];
		int size;
		void invalidate(int slot);
	public:
		int epoch;
		int offer(Request req);
		void beginEpoch();
		void clean();
		StreamFilter();

};
class Prefetcher {
  private:
	Request _nextReq;
	queue<u_int32_t> reqs;
	StreamFilter * streamFilter;

  public:
	Prefetcher();
	~Prefetcher();
	// should return true if a request is ready for this cycle
	bool hasRequest(u_int32_t cycle);

	// request a desired address be brought in
	Request getRequest(u_int32_t cycle);

	// this function is called whenever the last prefetcher request was successfully sent to the L2
	void completeRequest(u_int32_t cycle);

	void cpuRequest(Request req); 
};

#endif
